/*
 **                Copyright 2012, MARVELL SEMICONDUCTOR, LTD.
 ** THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.
 ** NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT
 ** OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE
 ** DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.
 ** THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,
 ** IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.
 **
 ** MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES,
 ** MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL
 ** SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.
 ** (MJKK), MARVELL ISRAEL LTD. (MSIL).
 */

package com.android.settings.bluetooth;

import java.lang.Object;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Set;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;

/*hisense*/
import java.util.Timer;
import java.util.TimerTask;

import com.android.settings.R;

public class BluetoothAutoPairConnManager implements Runnable {
	private static final String TAG = "BluetoothAutoPairConnManager";

	private static BluetoothAutoPairConnManager sInstance = null;
	private static Object sLock = new Object();

	private static final String ACTION_START_PAIRING = "com.marvell.bluetooth.START_PAIRING";
	private static final String ACTION_AUTO_PAIR_CONN_DONE = "com.marvell.bluetooth.AUTO_PAIR_CONN_DONE";
	private static final String ACTION_AUTO_PAIR_CONN_COMPLETED =
             "com.marvell.bluetooth.AUTO_PAIR_CONN_COMPLETED";
    private static final String ACTION_AUTO_PAIR_CONN_SKIP =
            "com.marvell.bluetooth.AUTO_PAIR_CONN_SKIP";
	private static short times = 0;
	private static short timeout = 0;
    // STATE
	private static final String STATE_NA = "state_na";
	private static final String STATE_WAIT_BT_TURN_ON = "state_wait_bt_turn_on";
	private static final String STATE_WAIT_BT_TURN_OFF = "state_wait_bt_turn_off";
	private static final String STATE_FIND_NEARBY = "state_find_nearby";
	private static final String STATE_WAIT_CONNECTED = "state_wait_connected";
	private static final String STATE_DEVICE_CONNECTED = "state_device_connected";

	private static final String STATE_CHECK_PAIR_DEV = "state_check_pair_dev";
	private static final String STATE_CHECK_CONN_DEV = "state_check_conn";

	private Context mContext = null;
	private Handler mHandler;
	private Toast mDevFoundToast = null;
	private Toast mDevBondedToast = null;
	private Toast mDevReConnectToast = null;
	private Toast mDevConnectFailToast = null;
	private Toast mDevConnectSuccessToast = null;

	private boolean mRunning = false;
	private Thread mThread = null;
	private LinkedList<BluetoothAutoPairConnManagerMsg> mMsgPool = null;
	private String mState = null;
	private LocalBluetoothAdapter mLocalAdapter = null;
	private CachedBluetoothDeviceManager mCachedDeviceManager = null;
	private String mRequestBtRcName = null;
	private String mDefaultBtRcNameArray[] = { "SONY NSG-MR5-U",
			"GTVController", "Hisense Vision Remote Control" };

	/*
	 * chenfeng change default RC from "SONY NSG-MR5-U" to
	 * "Hisense Pulse Remote Control", if you modify the name here please change
	 * the mERF6B10Fakename in CacheBluetoothDevice.java also.
	 */

	private class BluetoothAutoPairConnManagerMsg {
		// BluetoothAutoPairConnManagerMsg type
		public static final String MSG_NA = "msg_na";
		public static final String MSG_REQUEST_AUTO_PAIR_CONN = "msg_request_auto_pair_conn";
		public static final String MSG_CANCEL_AUTO_PAIR_CONN = "msg_cancel_auto_pair_conn";
		public static final String MSG_BT_TURN_ON_DONE = "msg_bt_turn_on_done";
		public static final String MSG_BT_TURN_OFF_DONE = "msg_bt_turn_off_done";
		public static final String MSG_BT_DEVICE_FOUND = "msg_bt_device_found";
		public static final String MSG_BT_DISCOVERY_FINISH = "msg_bt_discovery_finish";
		public static final String MSG_BT_DEVICE_CONNECTED = "msg_bt_device_connected";
		public static final String MSG_BT_DEVICE_BONDED = "msg_bt_device_BONDED";
		public static final String MSG_BT_DEVICE_CONNECTE_FAIL = "msg_bt_device_connect_fail";
		public static final String MSG_BT_DEVICE_RECONNECTE = "msg_bt_device_reconnect";
		public static final String MSG_CHECK_CONNECT_STATUS = "msg_check_connect_status";
		public static final String MSG_EXIT = "msg_exit";

		private String mMsgType = null;
		private String mParam = null;
		private Object mObjParam = null;

		public BluetoothAutoPairConnManagerMsg(String msgType, String param) {
			mMsgType = msgType;
			mParam = param;
			mObjParam = null;
		}

		public BluetoothAutoPairConnManagerMsg(String msgType, String param,
				Object obj) {
			mMsgType = msgType;
			mParam = param;
			mObjParam = obj;
		}

		public String getMsgType() {
			return mMsgType;
		}

		public String getParam() {
			return mParam;
		}

		public Object getObjParam() {
			return mObjParam;
		}

		public String toString() {
			return "[msgType: " + mMsgType + ", param: " + mParam
					+ ", mObjParam: " + mObjParam + "]";
		}
	}

	public static BluetoothAutoPairConnManager createInstance(Context context) {
		synchronized (sLock) {
			Log.i(TAG, "getInstance enter, sInstance = " + sInstance);
			if (null == sInstance) {
				sInstance = new BluetoothAutoPairConnManager(context);
			}

			Log.i(TAG, "getInstance leave, sInstance = " + sInstance);
		}

		return sInstance;
	}

	public static BluetoothAutoPairConnManager getInstance() {
		return sInstance;
	}

	private BluetoothAutoPairConnManager(Context context) {
		Log.i(TAG, "BluetoothAutoPairConnManager init enter");

		mContext = context;
		LocalBluetoothManager manager = LocalBluetoothManager
				.getInstance(mContext);
		if (null == manager) {
			// Bluetooth is not supported
			Log.e(TAG, "Bluetooth is not supported");
			mLocalAdapter = null;
			mCachedDeviceManager = null;
		} else {
			Log.i(TAG,
					"Bluetooth mLocalAdapter--->"
							+ manager.getBluetoothAdapter());
			mLocalAdapter = manager.getBluetoothAdapter();
			mCachedDeviceManager = manager.getCachedDeviceManager();
		}

		mHandler = new Handler();
		mDevFoundToast = Toast
				.makeText(mContext,
						R.string.bluetooth_auto_pair_conn_dev_found,
						Toast.LENGTH_SHORT);
		mDevBondedToast = Toast.makeText(mContext,
				R.string.bluetooth_auto_pair_conn_dev_bonded,
				Toast.LENGTH_SHORT);
		mDevReConnectToast = Toast.makeText(mContext, "ReConnect...",
				Toast.LENGTH_SHORT);
		mDevConnectFailToast = Toast.makeText(mContext,
				R.string.bluetooth_auto_pair_conn_dev_pair_conn_fail,
				Toast.LENGTH_SHORT);
		mDevConnectSuccessToast = Toast.makeText(mContext,
				R.string.bluetooth_auto_pair_conn_dev_conn_success,
				Toast.LENGTH_SHORT);

		setState(STATE_NA);
		mMsgPool = new LinkedList<BluetoothAutoPairConnManagerMsg>();
		mRunning = true;
		mThread = new Thread(this, TAG);
		mThread.start();

		Log.i(TAG, "BluetoothAutoPairConnManager init leave");
	}

	private void destroy() {
		Log.i(TAG, "destroy enter");

		synchronized (mMsgPool) {
			mMsgPool.clear();
		}

		synchronized (sLock) {
			sInstance = null;
		}

		Log.i(TAG, "destroy leave");
	}

	public void requestAutoPairConn(String btRCName) {
		Log.i(TAG, "requestAutoPairConn enter, btRCName = " + btRCName);

		synchronized (mMsgPool) {
			BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
					BluetoothAutoPairConnManagerMsg.MSG_REQUEST_AUTO_PAIR_CONN,
					btRCName);
			mMsgPool.addLast(msg);
			mMsgPool.notifyAll();
		}

		Log.i(TAG, "requestAutoPairConn leave");
	}

	public void notifyCancelAutoPairConn() {
		Log.i(TAG, "notifyCancelAutoPairConn enter");

		synchronized (mMsgPool) {
			BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
					BluetoothAutoPairConnManagerMsg.MSG_CANCEL_AUTO_PAIR_CONN,
					null);
			mMsgPool.addLast(msg);
			mMsgPool.notifyAll();
		}

		Log.i(TAG, "notifyCancelAutoPairConn leave");
	}

	public void notifyBTStateChanged(int state) {
		Log.i(TAG, "notifyBTStateChanged enter, state = " + state);
		String msgType = BluetoothAutoPairConnManagerMsg.MSG_NA;
		switch (state) {
		case BluetoothAdapter.STATE_ON:
			msgType = BluetoothAutoPairConnManagerMsg.MSG_BT_TURN_ON_DONE;
			break;
		case BluetoothAdapter.STATE_OFF:
			msgType = BluetoothAutoPairConnManagerMsg.MSG_BT_TURN_OFF_DONE;
			break;
		case BluetoothAdapter.STATE_TURNING_ON:
		case BluetoothAdapter.STATE_TURNING_OFF:
		default:
			Log.i(TAG, "do nothing here");
			break;
		}
		if (false == msgType.equals(BluetoothAutoPairConnManagerMsg.MSG_NA)) {
			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						msgType, null);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		}

		Log.i(TAG, "notifyBTStateChanged leave");
	}

	public void notifyDeviceReconnect(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyDeviceReconnect enter, device = " + device);

		if (null != device) {
			Log.i(TAG,
					"notifyDeviceReconnect device name = " + device.getName());
			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_RECONNECTE,
						null, device);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		} else {
			Log.e(TAG, "notifyDeviceReconnect device should not null");
		}

		Log.i(TAG, "notifyDeviceReconnect leave");
	}

	public void notifyDeviceFound(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyBTStateChanged enter, device = " + device);

		if (null != device) {
			Log.i(TAG, "notifyBTStateChanged device name = " + device.getName());
			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_FOUND,
						null, device);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		} else {
			Log.e(TAG, "notifyDeviceConnected device should not null");
		}

		Log.i(TAG, "notifyBTStateChanged leave");
	}

	public void notifyDeviceDiscoveryFinish() {
		Log.i(TAG, "notifyDeviceDiscoveryFinish enter");
		synchronized (mMsgPool) {
			BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
					BluetoothAutoPairConnManagerMsg.MSG_BT_DISCOVERY_FINISH,
					null);
			mMsgPool.addLast(msg);
			mMsgPool.notifyAll();
		}
		Log.i(TAG, "notifyDeviceDiscoveryFinish leave");
	}

	public void notifyDeviceConnected(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyDeviceConnected enter, device = " + device);

		if (null != device) {
			Log.i(TAG,
					"notifyDeviceConnected device name = " + device.getName());

			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_CONNECTED,
						null, device);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		} else {
			Log.e(TAG, "notifyDeviceConnected device should not null");
		}

		Log.i(TAG, "notifyDeviceConnected leave");
	}

	public void notifyDeviceBonded(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyDeviceBonded enter, device = " + device);
		if (null != device) {
			Log.i(TAG, "notifyDeviceBonded device name = " + device.getName());

			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_BONDED,
						null, device);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		} else {
			Log.e(TAG, "notifyDeviceBonded device should not null");
		}

		Log.i(TAG, "notifyDeviceBonded leave");
	}

	public void notifyDeviceConnectFail(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyDeviceConnectFail enter, device = " + device);
		if (null != device) {
			Log.i(TAG,
					"notifyDeviceConnectFail device name = " + device.getName());

			synchronized (mMsgPool) {
				BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
						BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_CONNECTE_FAIL,
						null, device);
				mMsgPool.addLast(msg);
				mMsgPool.notifyAll();
			}
		} else {
			Log.e(TAG, "notifyDeviceConnectFail device should not null");
		}

		Log.i(TAG, "notifyDeviceConnectFail leave");
	}

	public void notifyCheckConnectStatus(CachedBluetoothDevice device) {
		Log.i(TAG, "notifyCheckConnectStatus enter, device = " + device);

		synchronized (mMsgPool) {
			BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
					BluetoothAutoPairConnManagerMsg.MSG_CHECK_CONNECT_STATUS,
					null, device);
			mMsgPool.addLast(msg);
			mMsgPool.notifyAll();
		}

		Log.i(TAG, "notifyCheckConnectStatus leave");
	}

	public void notifyExit() {
		Log.i(TAG, "notifyExit enter");

		synchronized (mMsgPool) {
			BluetoothAutoPairConnManagerMsg msg = new BluetoothAutoPairConnManagerMsg(
					BluetoothAutoPairConnManagerMsg.MSG_EXIT, null);
			mMsgPool.addLast(msg);
			mMsgPool.notifyAll();
		}

		Log.i(TAG, "notifyExit leave");
	}

	public void run() {
		Log.i(TAG, "thread run enter");

		Object o = null;

		while (mRunning) {
			o = null;

			try {
				synchronized (mMsgPool) {
					if (mMsgPool.isEmpty()) {
						mMsgPool.wait();
					} else {
						o = mMsgPool.removeFirst();
					}
				}

				if ((null != o)
						&& (o instanceof BluetoothAutoPairConnManagerMsg)) {
					BluetoothAutoPairConnManagerMsg msg = (BluetoothAutoPairConnManagerMsg) o;
					processMsg(msg);
				}
			} catch (InterruptedException e) {
				Log.i(TAG, "mThread is interrupted, should exit....", e);
				mRunning = false;
				break;
			} catch (Exception e) {
				Log.e(TAG, "mThread got exception", e);
				mRunning = false;
				break;
			}
		}

		Log.i(TAG, "thread run leave");
	}

	private void processMsg(BluetoothAutoPairConnManagerMsg msg) {
		Log.i(TAG, "processMsg enter, mState = " + mState + ", msg = " + msg);
		String msgType = msg.getMsgType();
		String param = msg.getParam();
		Object objParam = msg.getObjParam();

		// NOTE: special for user cancel auto pair conn
		if (true == msgType
				.equals(BluetoothAutoPairConnManagerMsg.MSG_CANCEL_AUTO_PAIR_CONN)) {
			Log.i(TAG, "processMsg cancel auto pair conn");
			mRunning = false;
			destroy();
		} else {
			if (true == mState.equals(STATE_NA)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_REQUEST_AUTO_PAIR_CONN)) {
					processRequestAutoPairConn(param);
				} else {
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else if (true == mState.equals(STATE_WAIT_BT_TURN_OFF)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_TURN_OFF_DONE)) {
					handleBluetoothState();
				} else {
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else if (true == mState.equals(STATE_WAIT_BT_TURN_ON)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_TURN_ON_DONE)) {
					handleBluetoothState();
				} else {
				    Log.w(TAG, "bluetooth not turn on, timeout ="+timeout);
				    if(timeout < 3){
				        mHandler.postDelayed(new Runnable() {
			                public void run() {
			                    handleBluetoothState();
			                    timeout++;
			                }
			            }, 3000);
				    }else{
				        mContext.sendBroadcast(new Intent(ACTION_AUTO_PAIR_CONN_SKIP));
				        timeout = 0;
				    }
				    
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else if (true == mState.equals(STATE_FIND_NEARBY)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_FOUND)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					connectDevice(device);
				} else if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DISCOVERY_FINISH)) {
					handleBluetoothState();
				}else if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_CONNECTED)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					deviceConnected(device);
					mContext.sendBroadcast(new Intent(ACTION_AUTO_PAIR_CONN_COMPLETED));
				} else {
				    handleBluetoothState();
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else if (true == mState.equals(STATE_WAIT_CONNECTED)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_CONNECTED)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					deviceConnected(device);
				} else if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_BONDED)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					deviceBonded(device);
				} else if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_BT_DEVICE_CONNECTE_FAIL)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					deviceConnectFail(device);
                    
				} else if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_CHECK_CONNECT_STATUS)) {
					CachedBluetoothDevice device = (CachedBluetoothDevice) objParam;
					deviceConnectFail(device);
				} else {
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else if (true == mState.equals(STATE_DEVICE_CONNECTED)) {
				if (true == msgType
						.equals(BluetoothAutoPairConnManagerMsg.MSG_EXIT)) {
					Log.i(TAG, "processMsg device connect is done! exit!");

					exit();
				} else {
					Log.w(TAG, "processMsg current state " + mState
							+ " do not processMsg msgType " + msgType);
				}
			} else {
				Log.e(TAG, "processMsg unsupported state mState = " + mState);
			}
		}

		Log.i(TAG, "processMsg leave");
	}

	private void setState(String stateToSet) {
		Log.i(TAG, "setState enter, mState = " + mState + ", stateToSet = "
				+ stateToSet);

		mState = stateToSet;

		Log.i(TAG, "setState leave");
	}

	public void setStateToSkip() {

		mLocalAdapter.setBluetoothEnabled(false);
		mState = STATE_NA;
		Log.i(TAG, "setState skip");
	}

	private void processRequestAutoPairConn(String btRcName) {
		Log.i(TAG, "processRequestAutoPairConn enter, btRcName = " + btRcName);
		if (null != mLocalAdapter) {
			// Save the bluetooth remote control name
			setRequestBtRcName(btRcName);

			handleBluetoothState();
		} else {
			Log.e(TAG,
					"processRequestAutoPairConn mLocalAdapter should not be null!!");
		}
		Log.i(TAG, "processRequestAutoPairConn leave");
	}

	private CachedBluetoothDevice getBondedDevice() {
		Log.i(TAG, "getBondedDevice enter");

		CachedBluetoothDevice ret = null;
		Collection<CachedBluetoothDevice> cachedDevices = mCachedDeviceManager
				.getCachedDevicesCopy();
		Set<BluetoothDevice> btDevices = mLocalAdapter.getBondedDevices();
		if ((null != cachedDevices) && (null != btDevices)
				&& (false == btDevices.isEmpty())) {
			Log.d(TAG, "getBondedDevice cachedDevices = " + cachedDevices);
			Log.d(TAG, "getBondedDevice btDevices = " + btDevices);

			for (CachedBluetoothDevice device : cachedDevices) {
				BluetoothDevice btDevice = device.getDevice();
				if (btDevices.contains(btDevice)) {
					if (isRequestBtRc(device.getName())) {
						Log.d(TAG,
								"getBondedDevice got it. name is "
										+ device.getName());
						ret = device;
						break;
					}
				}
			}
		}

		Log.i(TAG, "getBondedDevice leave");

		return ret;
	}

	private void handleBluetoothState() {
		Log.i(TAG, "handleBluetoothState enter, mRequestBtRcName = "
				+ mRequestBtRcName);
		// 1. Check if bluetooth is enabled
		int btState = mLocalAdapter.getBluetoothState();
		Log.i(TAG, "handleBluetoothState btState = " + btState);
		switch (btState) {
		case BluetoothAdapter.STATE_TURNING_ON:
			// Wait BT turn on done
			setState(STATE_WAIT_BT_TURN_ON);
			break;
		case BluetoothAdapter.STATE_ON:
			// send broadcast ACTION_START_PAIRING
			sendStartPairingBroadcast();
			handleStateOn();
			break;
		case BluetoothAdapter.STATE_TURNING_OFF:
			// Wait BT turn off done
			setState(STATE_WAIT_BT_TURN_OFF);
			break;
		case BluetoothAdapter.STATE_OFF:
		default:
			// Turn on the BT
     		Log.i(TAG, "handleBluetoothState, switch default");
			mLocalAdapter.setBluetoothEnabled(false);
			mLocalAdapter.setBluetoothEnabled(true);
			// Wait BT turn on done
			setState(STATE_WAIT_BT_TURN_ON);
			break;
		}
		Log.i(TAG, "handleBluetoothState leave");
	}

	private void handleStateOn() {
		CachedBluetoothDevice device = getBondedDevice();
		Log.i(TAG, "handleStateOn enter, device = " + device);
		if (null == device) {
			Log.i(TAG, "handleStateOn go to find nearby--->mAdapter:"
					+ mLocalAdapter);
			// Go to find nearby
            mLocalAdapter.startScanning(true,mContext);
			setState(STATE_FIND_NEARBY);
		} else {
			if (false == device.isConnected()) {
				Log.i(TAG, "handleStateOn go to connect the device");
				connectDevice(device);
			} else {
				Log.i(TAG, "handleStateOn device " + device
						+ " has already connected");
				deviceConnected(device);
			}
		}
		Log.i(TAG, "handleStateOn leave");
	}

	private void connectDevice(final CachedBluetoothDevice device) {
		Log.i(TAG, "connectDevice enter, device = " + device);
		if (true == isRequestBtRc(device.getName())) {
			// Show device found toast
			mHandler.post(new Runnable() {
				public void run() {
					mDevFoundToast.setGravity(Gravity.BOTTOM, 0, 0);
					;
					mDevFoundToast.show();
				}
			});
			Log.i(TAG, "!!!!!!Call device.startPairing()!!!!!!!!");
			if (!device.startPairing()) {
			    Log.i(TAG, "!!!fail to start pairing!!!!!!!!");
				device.unpair();
				Log.i(TAG, "!!!unpaired!!!!!!!!");
	            mLocalAdapter.startScanning(true, mContext);
	            setState(STATE_FIND_NEARBY);
			    return;
				//deviceReconnect(device);
			}
			setState(STATE_WAIT_CONNECTED);
			// Set a timeout to check if the connect done
			new Thread() {
				public void run() {
					Log.i(TAG, "Check connect status thread enter");
					try {
						Thread.sleep(10 * 1000);
					} catch (Exception e) {
						Log.i(TAG, "got e ", e);
					}

					Log.i(TAG, "notifyCheckConnectStatus mState = " + mState);
					if (STATE_WAIT_CONNECTED == mState) {
						Log.i(TAG, "Go to notifyCheckConnectStatus device = "
								+ device);
						notifyCheckConnectStatus(device);
					}
					Log.i(TAG, "Check connect status thread leave");
				}
			}.start();
		}
		Log.i(TAG, "connectDevice leave");
	}

	private void deviceConnected(CachedBluetoothDevice device) {
		Log.i(TAG, "deviceConnected enter, device = " + device);
		if (true == isRequestBtRc(device.getName())) {
			// Show connect success toast
			mHandler.post(new Runnable() {
				public void run() {
					mDevConnectSuccessToast.setGravity(Gravity.BOTTOM, 0, 0);
					mDevConnectSuccessToast.show();
				}
			});

			setState(STATE_DEVICE_CONNECTED);
			notifyExit();
		}
		Log.i(TAG, "deviceConnected leave");
	}

	private void deviceBonded(CachedBluetoothDevice device) {
		Log.i(TAG, "deviceBonded enter, device = " + device);
		if (true == isRequestBtRc(device.getName())) {
			// Show bonded toast
			mHandler.post(new Runnable() {
				public void run() {
					mDevBondedToast.setGravity(Gravity.BOTTOM, 0, 0);
					mDevBondedToast.show();
				}
			});
		}
		Log.i(TAG, "deviceBonded leave");
	}

	// if we found the goal device is connected, need exit(),please note we only
	// can use profile status to judge
	private void deviceConnectFail(CachedBluetoothDevice device) {
		Log.i(TAG, "deviceConnectFail enter, device = " + device);
		times++;
		if (true == isRequestBtRc(device.getName())) {
			// Show connect fail toast, try again
		    if (times > 5 ){
    		    mHandler.post(new Runnable() {
    				public void run() {
    					mDevConnectFailToast.setGravity(Gravity.BOTTOM, 0, 0);
    					mDevConnectFailToast.show();
    				}
    			});
				mContext.sendBroadcast(new Intent(ACTION_AUTO_PAIR_CONN_COMPLETED));
		    }
			handleBluetoothState();
		}else{
			handleBluetoothState();
		}
		Log.i(TAG, "deviceConnectFail leave");
		times %=100;
	}

	private void sendStartPairingBroadcast() {
		Log.i(TAG, "sendStartPairingBroadcast enter");

		Intent intent = new Intent(ACTION_START_PAIRING);
		Log.i(TAG, "sendStartPairingBroadcast send broadcast " + intent);
		mContext.sendBroadcast(intent);

		Log.i(TAG, "sendStartPairingBroadcast leave");
	}

	private void exit() {
		Log.i(TAG, "exit enter");

		new Timer().schedule(new TimerTask() {
			public void run() {
				Intent intent = new Intent(ACTION_AUTO_PAIR_CONN_DONE);
				Log.i(TAG, "exit send broadcast " + intent);
				mContext.sendStickyBroadcast(intent);
				this.cancel();
			}
		}, 4500);

		mRunning = false;
		destroy();
		Log.i(TAG, "exit leave");
	}

	private void setRequestBtRcName(String btRcNameToSet) {
		Log.i(TAG, "setRequestBtRcName enter, mRequestBtRcName = "
				+ mRequestBtRcName + ", btRcNameToSet = " + btRcNameToSet);
		mRequestBtRcName = btRcNameToSet;
		Log.i(TAG, "setRequestBtRcName leave");
	}

	private boolean isRequestBtRc(String destRcName) {
		Log.i(TAG, "isRequestBtRc enter, mRequestBtRcName = "
				+ mRequestBtRcName + ", destRcName = " + destRcName);
		boolean ret = false;

		if (null != mRequestBtRcName) {
			if (-1 != destRcName.indexOf(mRequestBtRcName)) {
				ret = true;
			}
		} else {
			Log.e(TAG, "isRequestBtRc mRequestBtRcName should not be null");
		}

		if (false == ret) {
			Log.i(TAG, "isRequestBtRc go to try default bt rc");
			for (String defaultBtRc : mDefaultBtRcNameArray) {
				Log.i(TAG, "isRequestBtRc defaultBtRcf = " + defaultBtRc
						+ ", destRcName = " + destRcName);
				if (-1 != destRcName.indexOf(defaultBtRc)) {
					ret = true;
					break;
				}
			}
		}

		Log.i(TAG, "isRequestBtRc leave, ret = " + ret);
		return ret;
	}

	public boolean isHisenseRequestBtRc(String destRcName) {
		Log.i(TAG, "isRequestBtRc enter, mRequestBtRcName = "
				+ mRequestBtRcName + ", destRcName = " + destRcName);
		boolean ret = false;

		if (null != mRequestBtRcName) {
			if (-1 != destRcName.indexOf(mRequestBtRcName)) {
				ret = true;
			}
		} else {
			Log.e(TAG, "isRequestBtRc mRequestBtRcName should not be null");
		}

		if (false == ret) {
			Log.i(TAG, "isRequestBtRc go to try default bt rc");
			for (String defaultBtRc : mDefaultBtRcNameArray) {
				Log.i(TAG, "isRequestBtRc defaultBtRcf = " + defaultBtRc
						+ ", destRcName = " + destRcName);
				if (-1 != destRcName.indexOf(defaultBtRc)) {
					ret = true;
					break;
				}
			}
		}

		Log.i(TAG, "isRequestBtRc leave, ret = " + ret);
		return ret;
	}
}
